#include <string.h>
#include "stdinc.h"
#include "mcu.h"
#include "netutils.h"


uint32_t getU32(const void *stream) {
	uint8_t *buf = (uint8_t*)stream;
	return MAKE_DWORD(buf[0], buf[1], buf[2], buf[3]);
}

uint16_t getU16(const void *stream) {
	uint8_t *buf = (uint8_t*)stream;
	return MAKE_WORD(buf[0], buf[1]);
}


/// 中断重入层级表
uint8_t _IrqReentry[IRQn_MAX] = {0};
/// 中断重入层级曾经的最大值
uint8_t _IrqReentryMax = 0;


void mcu_init() {
	// 初始化中断重入层级表
	memset(_IrqReentry, 0, sizeof(_IrqReentry));
	_IrqReentryMax = 0;
}

/**
 * 参数版 gpio_config()
 */
esp_err_t GPIO_Config(gpio_num_t pin, gpio_mode_t mode, gpio_pullup_t pull_up_en, gpio_pulldown_t pull_down_en, gpio_int_type_t intr_type) {
    gpio_config_t cfg = {
        .pin_bit_mask   = (1ULL<<pin),
        .mode           = mode,
        .pull_up_en     = pull_up_en,
        .pull_down_en   = pull_down_en,
        .intr_type      = intr_type
    };
    return gpio_config(&cfg);
}

/**
 * 可能的重启原因有：
ESP_RST_UNKNOWN,    //!< Reset reason can not be determined
ESP_RST_POWERON,    //!< Reset due to power-on event
ESP_RST_EXT,        //!< Reset by external pin (not applicable for ESP32)
ESP_RST_SW,         //!< Software reset via esp_restart
ESP_RST_PANIC,      //!< Software reset due to exception/panic
ESP_RST_INT_WDT,    //!< Reset (software or hardware) due to interrupt watchdog
ESP_RST_TASK_WDT,   //!< Reset due to task watchdog
ESP_RST_WDT,        //!< Reset due to other watchdogs
ESP_RST_DEEPSLEEP,  //!< Reset after exiting deep sleep mode
ESP_RST_BROWNOUT,   //!< Brownout reset (software or hardware)
ESP_RST_SDIO,       //!< Reset over SDIO
*/
bool osIsAbnormalReboot() {
	esp_reset_reason_t reason = osGetResetReason();
	switch(reason) {
		case ESP_RST_POWERON:
		case ESP_RST_SW:
		case ESP_RST_DEEPSLEEP:
			return FALSE;
		default:
			return TRUE;
	}
}


/// 常用内置硬件接口地址
const Ship2Addr Ship2Addr_NULL  = { .bytes = {Ship2AddrType_NULL} };
const Ship2Addr Ship2Addr_UART0 = { .bytes = {Ship2AddrType_P2P|0x01, 0x00} };
const Ship2Addr Ship2Addr_UART1 = { .bytes = {Ship2AddrType_P2P|0x01, 0x01} };
const Ship2Addr Ship2Addr_UART2 = { .bytes = {Ship2AddrType_P2P|0x01, 0x02} };
const Ship2Addr Ship2Addr_UART3 = { .bytes = {Ship2AddrType_P2P|0x01, 0x03} };
const Ship2Addr Ship2Addr_UART4 = { .bytes = {Ship2AddrType_P2P|0x01, 0x04} };
const Ship2Addr Ship2Addr_UART5 = { .bytes = {Ship2AddrType_P2P|0x01, 0x05} };
const Ship2Addr Ship2Addr_SPI0 	= { .bytes = {Ship2AddrType_P2P|0x01, 0x06} };
const Ship2Addr Ship2Addr_SPI1 	= { .bytes = {Ship2AddrType_P2P|0x01, 0x07} };
const Ship2Addr Ship2Addr_SPI2 	= { .bytes = {Ship2AddrType_P2P|0x01, 0x08} };
const Ship2Addr Ship2Addr_SPI3 	= { .bytes = {Ship2AddrType_P2P|0x01, 0x09} };
const Ship2Addr Ship2Addr_I2C0 	= { .bytes = {Ship2AddrType_P2MP|0x01, 0x00} };
const Ship2Addr Ship2Addr_I2C1 	= { .bytes = {Ship2AddrType_P2MP|0x01, 0x01} };
const Ship2Addr Ship2Addr_I2C2 	= { .bytes = {Ship2AddrType_P2MP|0x01, 0x02} };
const Ship2Addr Ship2Addr_I2C3 	= { .bytes = {Ship2AddrType_P2MP|0x01, 0x03} };

/// 本机地址常量
const Ship2Addr Ship2Addr_P2P    = { .bytes = {Ship2AddrType_P2P|0x00} };
const Ship2Addr Ship2Addr_RFComm = { .rfcomm = { .type = Ship2AddrType_RFComm, .devId = hton32(DEVICE_ID) } };

/// 广播地址常量
const Ship2Addr Ship2BroadcastAddr_ALL        = { .bytes = {0xF0} };
const Ship2Addr Ship2BroadcastAddr_ALL_P2P    = { .bytes = {0xF1, Ship2IfType_P2P} };
const Ship2Addr Ship2BroadcastAddr_ALL_P2MP   = { .bytes = {0xF1, Ship2IfType_P2MP} };
const Ship2Addr Ship2BroadcastAddr_ALL_RFComm = { .bytes = {0xF1, Ship2IfType_RFComm} };

const Ship2Addr Ship2BroadcastAddr_P2P    = { .bytes = {Ship2AddrType_P2P|0x00} };
const Ship2Addr Ship2BroadcastAddr_P2MP   = { .bytes = {Ship2AddrType_P2MP|0x04, 0xFF, 0xFF, 0xFF, 0xFF} };
const Ship2Addr Ship2BroadcastAddr_RFComm = { .bytes = {Ship2AddrType_RFComm|0x04, 0xFF, 0xFF, 0xFF, 0xFF} };


// 接口类型名称映射表
static const char* Ship2IfTypeNameMap[] = {
	"NULL"      ,
	"P2P"       ,
	"P2MP"      ,
	"RFComm"    ,
	"TCP"       ,
	"UDP"       ,
	"SPP"       ,
	"BLEBeacon" ,
	"WiFiBeacon",
	"LoRa"      ,
	"Zigbee"    ,
	"RF433"     ,
	"RF315"     ,
	"IR"        ,
	"HXDIR"     ,
	"MAX"       ,
};

const char* Ship2Addr_toString(const Ship2Addr* addr) {
	static char buf[64];
	switch(addr->st.ifType) {
	case Ship2IfType_NULL      : return "NULL";
	case Ship2IfType_P2P   	   : return "P2P";
	case Ship2IfType_P2MP      : snprintf(buf, 64, "P2MP[]"); return buf;
	case Ship2IfType_RFComm    : snprintf(buf, 64, "RFComm[%08X]", ntoh32(addr->rfcomm.devId)); return buf;
	case Ship2IfType_TCP       : return "TCP";
	case Ship2IfType_UDP       : snprintf(buf, 64, "UDP[%s:%d]", ip4_u32_to_str(addr->udp.ipv4, NULL), addr->udp.port); return buf;
	case Ship2IfType_SPP       : return "SPP"       ;
	case Ship2IfType_BLEBeacon : return "BLEBeacon" ;
	case Ship2IfType_WiFiBeacon: return "WiFiBeacon";
	case Ship2IfType_LoRa      : return "LoRa"      ;
	case Ship2IfType_Zigbee    : return "Zigbee"    ;
	case Ship2IfType_RF433     : return "RF433"     ;
	case Ship2IfType_RF315     : return "RF315"     ;
	case Ship2IfType_IR        : return "IR"        ;
	case Ship2IfType_HXDIR     : return "HXDIR"     ;
	case Ship2IfType_MAX       : return "MAX"       ;
	}
	return buf;
}

bool Ship2Addr_p2p(const Ship2Addr* addr) {
	return Ship2IfType_IS_P2P(addr->st.ifType) && (addr->st.addrSize == 0);
}

bool Ship2Addr_same(const Ship2Addr* addr1, const Ship2Addr* addr2) {
	return memcmp(addr1, addr2, 1 + addr1->st.addrSize) == 0;
}

void Ship2Addr_copy(Ship2Addr* addr1, const Ship2Addr* addr2) {
    memset(addr1, 0, sizeof(Ship2Addr));
    memcpy(addr1, addr2, 1 + addr2->st.addrSize);
}
